是一種用於在網絡上安全傳輸信息的開放標準。它通常用於身份驗證和授權方面的應用,尤其在Web應用程序和移動應用程序中廣泛使用。JWT的主要特點是它是一種緊湊的、自包含的數據格式,可以在各種系統之間輕鬆傳遞信息,同時確保數據的完整性和安全性。
以下是JWT的一些關鍵特點和組成部分:
JWT使用JSON(JavaScript Object Notation)作為其數據格式,這使得它易於理解和使用。
JWT包含了所有必要的信息,因此不需要在伺服器上存儲會話信息或狀態信息。這減輕了伺服器的負擔,並使應用程序可以更容易地擴展。
JWT可以使用數字簽名進行驗證,以確保其內容在傳輸過程中未被篡改。這有助於確保數據的完整性和安全性。
包含了有關令牌的元數據,例如使用的簽名算法(例如HS256或RS256)。
包含了令牌的主要信息,通常包括使用者ID、過期時間、發行者等等。
用於驗證令牌的簽名部分,確保令牌在傳輸過程中沒有被篡改。
延續上一篇
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
</dependency>
這裡將處理jwt相關作業,如:提取用戶,解析聲明與生成token等等
@Service
@Slf4j
public class JwtService {
    // Token有效期限 (設定15分鐘過期)
    private Long EXPIRATION_TIME = 60*60*1000; //單位ms
    //BASE64編碼的密鑰
    private String SECRET_KEY = "546A55A71347A254462D4......";
    /**
     * 從JWT令牌中提取用戶名
     */
    public String extractUsername(String token) {
        return extractClaim(token, Claims::getSubject);
    }
    /**
     * 提取JWT令牌中的任何聲明(Claims),並通過提供的Function來解析它們。
     */
    public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = extractAllClaims(token);
        return claimsResolver.apply(claims);
    }
    public String generateToken(UserDetails userDetails) {
        return generateToken(new HashMap<>(), userDetails);
    }
    /**
     * 簽發Token
     */
    public String generateToken(
        Map<String, Object> extractClaims,
        UserDetails userDetails
    ) {
        return Jwts
            .builder()
            .setClaims(extractClaims)
            .setSubject(userDetails.getUsername()) //以Username做為Subject
            .setIssuedAt(new Date(System.currentTimeMillis()))
            .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
            .signWith(getSignInKey(), SignatureAlgorithm.HS256)
            .compact();
    }
    /**
     * 驗證Token有效性,比對JWT和UserDetails的Username(Email)是否相同
     * @return 有效為True,反之False
     */
    public boolean isTokenValid(String token, UserDetails userDetails) {
        final String username = extractUsername(token);
        return (username.equals(userDetails.getUsername())) && !isTokenExpired(token);
    }
    /**
     * 驗證token是否過期
     */
    private boolean isTokenExpired(String token) {
        final Date expirationDate = extractExpiration(token);
//        return extractExpiration(token).before(new Date());
        return expirationDate != null && expirationDate.before(new Date());
    }
    private Date extractExpiration(String token) {
        return extractClaim(token, Claims::getExpiration);
    }
    /**
     * 獲取令牌中所有的聲明將其解析
     * @return 令牌中所有的聲明
     */
    private Claims extractAllClaims(String token) {
        return Jwts
            .parserBuilder()
            .setSigningKey(getSignInKey())
            .build()
            .parseClaimsJws(token)
            .getBody();
    }
    /**
     * 獲取JWT簽名的密鑰
     */
    private Key getSignInKey() {
        byte[] keyBytes = Decoders.BASE64.decode(SECRET_KEY);
        return Keys.hmacShaKeyFor(keyBytes);
    }
}
下一篇要介紹Jwt認證過濾器